package com.day20_reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @ClassName: reflect_test01
 * @Author: zw
 * @Description: 出百万拳，行万里路；
 * @Create 2024/3/31-09:07
 * @Version 1.0
 */
public class reflect_test01 {
    // 获取Student类的构造方法
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // Student.class 返回Student类对应的class对象
        Class<Stduent> c1 = Stduent.class;

        // 调用Student对象的getClass对象， 返回Student类对应的class对象
        Stduent stduent = new Stduent();
        Class<? extends Stduent> c2 = stduent.getClass();
        System.out.println(c1 == c2);

        // 使用Class类中的静态方法forName（String className），该方法需要传入字符串参数，
        // 该字符串参数的值是某个类的全路径，
        Class<?> c3 = Class.forName("com.day20_reflect.Stduent");
        System.out.println(c1==c3);
        // getConstructors 只能拿到公共的构造方法数组, *** 只能拿到公共的构造方法 ***
        Constructor<?>[] constructors = c3.getConstructors();
        System.out.println("getConstructors 构造方法数组");
        for(Constructor con: constructors) {
            System.out.println(con);
        }
        // declaredConstructors 这个方法可以拿到所有的构造方法（包括私有和公共,默认）的数组
        c3.getDeclaredConstructors();
        Constructor<?>[] declaredConstructors = c3.getDeclaredConstructors();
        System.out.println("declaredConstructors 这个方法可以拿到所有的构造方法（包括私有和公共， 默认）的数组");
        for (Constructor con: declaredConstructors) {
            System.out.println(con);
        }

        // 获取单个公共构造方法对象
        // 参数是你要获取的构造方法的参数个数，和数据类型对应的字节码对象
        Constructor<?> constructor = c3.getConstructor();
        System.out.println("getConstructor --- 参数是你要获取的构造方法的参数个数，和数据类型对应的字节码对象");
        // 反映: 通过构造方法创建对象
        // 创建无参数的对象
        Object o = constructor.newInstance();
        System.out.println(o); // 重写了 toString方法
        // 创建带参的对象
        Constructor<?> constructor1 = c3.getConstructor(int.class);
        Object o1 = constructor1.newInstance(10);
        System.out.println(o1);

        // test练习
        // 1. 用获取到默认的构造方法  c3.getDeclaredConstructor(String.class, int.class);
        // 2. 反射：用默认的构造方法 创建对象
        Constructor<?> declaredConstructor = c3.getDeclaredConstructor(String.class, int.class);
        Object o2 = declaredConstructor.newInstance("林青霞", 30);
        System.out.println("----");
        System.out.println(o2);

        // 暴力反射
        // 1. 得到私有的构造方法
        Constructor<?> declaredConstructor1 = c3.getDeclaredConstructor(String.class);
        // 2. 暴力反射钱 通过设置setAccessible(true) 让其取消访问检查
        declaredConstructor1.setAccessible(true);
        // 反射去创建对象
        Object o3 = declaredConstructor1.newInstance("张曼玉");
        System.out.println("暴力反射");
        System.out.println(o3);
    }
}
